// Krinkle.m --

#import "math.h"
#import <appkit/NXBitmapImageRep.h>
#import "Krinkle.h"

@implementation Krinkle

long random(),
force();

#define YMAX 200
#define XMAX 320
#define YMAX1 50
#define XMAX1 50
#define SCALE 256
#define LSCALE 8
#define SCmax 32767
#define SCmin -32768

typedef char char_image[YMAX1][XMAX1];
Krinkle *Self;

- init
{	[super init];
#	define FC(x) ((int)((x)*SCALE))		/* all f24.8*/
					// user interface:
	krinkle = FC(15.);
	bump = FC(8.);
	spring = FC(2.);
	damping = FC(.1);
	//damping = 0.1;

	agc = 0x10000;
	agv = 0;

	Xf = &z1;	Xt = &z2;
	Vf = &v1;	Vt = &v2;
	return [self Randomize :nil];
}

- Randomize :sender;
{	int i, j;
	for (i=0; i<c_yh; i++)
		for (j=0; j<c_xw; j++)
			z1[i][j] = random() % (10);		//?? n?
	return self;
}

- (void)compute
{	register int Iold;
	register long f, v, p;
	register int_image *pXf, *pVf;
	int pmax, pmin;
	int_image *pXt, *pVt;
	int x, y;
	int_image *tmp;
	screen_image *pS;

	Self = self;
	pmax = -0xffff; pmin = 0xffff;
	for (y=1; y<c_yh-1; y++)
	{	pXf = (int_image *)&(*Xf)[y][1];
		pXt = (int_image *)&(*Xt)[y][1];
		pVf = (int_image *)&(*Vf)[y][1];
		pVt = (int_image *)&(*Vt)[y][1];
		pS = (screen_image *)&image[y][1];
		for (x=1; x<c_xw-1; x++)
		{	Iold = (*pXf)[0][0];
			f = (force((*pXf)[-1][0],Iold,(*pXf)[1][0])
				+ force((*pXf)[0][-1],Iold,(*pXf)[0][1])
				- (long)damping * (*pVf)[0][0] ) >>LSCALE;
			(*pVt)[0][0] = v = (*pVf)[0][0] + f;
			(*pXt)[0][0] = p=(*pXf)[0][0] + (v>>LSCALE);/**/
		/*	(*pXt)[0][0] = p=((*pXf)[0][0] + v)>>LSCALE;/**/
	
			if (p > SCmax) p = SCmax;
			if (p < SCmin) p = SCmin;
			if (p > pmax) pmax = p;
			if (p < pmin) pmin = p;
	//		(*pS)[0][0][0] = ((Iold-agv) * agc) >>8;
	ADD BACK!!!
		
			pXt = (int_image *)&(*pXt)[0][1];
			pXf = (int_image *)&(*pXf)[0][1];
			pVt = (int_image *)&(*pVt)[0][1];
			pVf = (int_image *)&(*pVf)[0][1];
			pS  = (screen_image *)&(*pS) [0][1];
	}	}
	agc = 0x10000 / (pmax-pmin+1);
	agv = pmin;
	tmp = Xf; Xf = Xt; Xt = tmp;
	tmp = Vf; Vf = Vt; Vt = tmp;
}

#define randm(x) (( ((int)random()) % (2*x-1) )-x)
#define bumpy(x) (x < -SCALE)? 0:\
		 (x<0)? -SCALE-x:\
		 (x==0)? randm(SCALE):\
		 (x< SCALE)? SCALE-d:\
		 0

long
force(a,b,c)
register int a, /* lesser index point */
	     b, /* this index point */
	     c; /* next index point */
		/* all i12.4 */
{	register int d, e;
	d = b - a;	/* this is the bump that causes all the problems: */
	e = c - b;
	d = bumpy(d);			/*__ |\__*/
	e = bumpy(e);			/*  \|   */

	return  ( Self->krinkle * (a-2*b+c)		/* 2'nd derivative */
		+ Self->bump * (d - e) 			/* 1'st derivative */
		- Self->spring * b );			/* position */
}	


- drawSelf:(const NXRect *)rects :(int)rectCount
{	//k2 = (float)[Healthy2Ill floatValue];
	if (bitmap == 0)
	{	bitmap = [[NXBitmapImageRep alloc] 		initData:(unsigned char *)image 
				pixelsWide :c_xw					pixelsHigh :(int)c_yh
				bitsPerSample :8					samplesPerPixel :Ncolors
				hasAlpha :NO						isPlanar :NO
				colorSpace:Ncolors>1? NX_RGBColorSpace:NX_OneIsWhiteColorSpace
				bytesPerRow :0					bitsPerPixel :0];
		[self setOpaque:YES];
		[self compute];
		[self start :nil];
	}
	[bitmap drawIn :&bounds];
	return self;
}

@end
